use mongodb::bson::doc;
use mongodb::Collection;
use mongodb::{options::ClientOptions, Client};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct User {
    name: String,
    age: i32,
}

/**
 * MongoDB 数据库中创建一个新的集合
 *
 * @param {Client} client - 连接到MongoDB数据库的客户端
 * @param {string} db_name - 数据库的名称
 * @param {string} coll_name - 集合的名称
 */
#[allow(dead_code)]
async fn create_collection(client: &Client, db_name: &str, coll_name: &str) {
    let db = client.database(db_name);
    db.create_collection(coll_name, None).await.unwrap();
}

/**
 * MongoDB 数据库中插入一个新的文档
 * @param {Client} client - 连接到MongoDB数据库的客户端
 * @param {string} db_name - 数据库的名称
 * @param {string} coll_name - 集合的名称
 */
#[allow(dead_code)]
async fn insert_document(client: &Client, db_name: &str, coll_name: &str) {
    let db = client.database(db_name);
    let coll: mongodb::Collection<_> = db.collection(coll_name);
    let doc = doc! { "name": "John", "age": 30 };
    coll.insert_one(doc, None).await.unwrap();
}

/**
 * MongoDb 数据库中检索文档
 *
 * @param {Client} client - 连接到MongoDB数据库的客户端
 * @param {string} db_name - 数据库的名称
 * @param {string} coll_name - 集合的名称
 */
async fn get_document(client: &Client, db_name: &str, coll_name: &str) {
    let db = client.database(db_name);
    let coll: Collection<_> = db.collection::<User>(coll_name);
    let filter = doc! { "name": "John"};
    let result = coll.find_one(Some(filter), None).await.unwrap();

    // 打印检索到的文档
    match result {
        Some(doc) => println!("{:?}", doc),
        None => println!("No documents found"),
    }
}

/**
 * 测试：向 MongoDB 数据库中插入一个新的文档
 */
#[allow(dead_code)]
async fn test_insert() {
    let client_options = ClientOptions::parse("mongodb://localhost:27017")
        .await
        .unwrap();
    let client = Client::with_options(client_options).unwrap();
    let db_name = "fly-test";
    let coll_name = "rust";
    insert_document(&client, db_name, coll_name).await;
}

/**
 * 测试：从 MongoDb 数据库读取一个文档
 */
async fn test_read() {
    let client_options = ClientOptions::parse("mongodb://localhost:27017")
        .await
        .unwrap();
    let client = Client::with_options(client_options).unwrap();
    let db_name = "fly-test";
    let coll_name = "rust";
    get_document(&client, db_name, coll_name).await;
}

#[tokio::main]
async fn main() {
    test_read().await;
    println!("Runtime terminated.");
}
